home *** CD-ROM | disk | FTP | other *** search
- VECTORS SEGMENT AT 0H ;Set up segment to intercept Interrupts
- ORG 9H*4 ;The keyboard Interrupt
- KEYBOARD_INT_VECTOR LABEL DWORD
- ORG 1CH*4 ;Timer Interrupt
- TIMER_VECTOR LABEL DWORD
- VECTORS ENDS
-
- ROM_BIOS_DATA SEGMENT AT 40H ;The ROM BIOS data area in low memory
- ORG 1AH ;This is where the keyboard buffer is.
- ROM_BUFFER_HEAD DW ? ;The position of the buffer's head
- ROM_BUFFER_TAIL DW ? ;And tail.
- KB_BUFFER DW 16 DUP (?) ;Reserve space for the buffer itself
- KB_BUFFER_END LABEL WORD ;Buffer's end is stored here.
- ROM_BIOS_DATA ENDS
-
- CODE_SEG SEGMENT ;Begin the Code segment holding the programs
- ASSUME CS:CODE_SEG
- ORG 100H ;Com files start at ORG 100H
- BEGIN: JMP INIT_VECTORS ;Skip over data area
-
- COPY_RIGHT DB '(C) 1984 S. Holzner' ;The Author's signature
- KEYS DW 30 DUP(0) ;The keys we replace
- FINISHED_FLAG DB 1 ;If not finished, timer will stuff buffer
- COMMANDS DW 1530 DUP(0) ;Scan and ASCII codes of commands
- COMMAND_INDEX DW 1 ;Stores position in command (for timer)
- ROM_KEYBOARD_INT DD 1 ;Called to interpret keyboard signals
- ROM_TIMER DD 1 ;The Timer interrupt's address
-
- INTERCEPT_KEYBOARD_INT PROC NEAR ;Here it is.
- ASSUME DS:NOTHING ;Free DS
- PUSH DS ;Save all used registers
- PUSH SI
- PUSH DI
- PUSH DX
- PUSH CX
- PUSH BX
- PUSH AX
- PUSHF ;Pushf for Keyboard Int's IRET
- CALL ROM_KEYBOARD_INT ;Have new key put into keyboard buffer
- ASSUME DS:ROM_BIOS_DATA ;Set up to point at keyboard buffer.
- MOV AX,ROM_BIOS_DATA
- MOV DS,AX
-
- MOV BX,ROM_BUFFER_TAIL ;Was there a character? If Tail equals
- CMP BX,ROM_BUFFER_HEAD ; Head then no real character typed.
- JNE NEWCHAR
- JMP NO_NEW_CHARACTERS ;Jump out, no new characters.
- NEWCHAR:SUB BX,2 ;Move back two bytes from tail;
- CMP BX,OFFSET KB_BUFFER ;Do we have to wrap?
- JAE NO_WRAP ;No
- MOV BX,OFFSET KB_BUFFER_END ;Wrap by moving two bytes
- SUB BX,2 ; before buffer end.
- NO_WRAP:MOV AX,[BX] ;Get the character into AX
-
- CMP FINISHED_FLAG,1 ;Done stuffing the buffer with last command?
- JE FIN ;Yes, proceed
- JMP NO_NEW_CHARACTERS ;No, leave.
-
- FIN: MOV FINISHED_FLAG,1 ;Assume we'll finish
-
- LEA SI,KEYS ;Point source index at keys to replace
- MOV CX,30 ;Loop over all of them
- LOOPER: CMP AX,CS:[SI] ;Match to given key (in AX)?
- JE FOUND ;Yes, key found, continue on.
- ADD SI,2 ;Point to next key to check it.
- LOOP LOOPER ;Go back for next one.
- JMP NO_NEW_CHARACTERS ;Loop finished without match - leave.
-
- FOUND: CLI ;Turn off hardware (timer, keyboard) Interrupts
- LEA SI,COMMANDS ;Set up to read command
- NEG CX ;Find the location of first word of command
- ADD CX,30
- MOV AX,CX
- MOV CX,102
- MUL CL
- ADD SI,AX
- MOV COMMAND_INDEX,SI ;And move it into Command_Index
-
- STUFF: MOV AX,CS:[SI] ;Here we go - get ready to stuff word in buffer.
- ADD SI,2 ;Point to the command's next character
- CMP AX,0 ;Is it a zero? (End of command)
- JE NO_NEW_CHARACTERS ;Yes, leave with Finished_Flag=1
- MOV DX,BX ;Find position in buffer from BX
- ADD DX,2 ;Move to next position for this word
- CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
- JL NO_WRAP2 ;No, don't wrap
- MOV DX,OFFSET KB_BUFFER ;Wrap
- NO_WRAP2:
- CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
- JE BUFFER_FULL ;Time to leave, set Finished_Flag=0.
- ADD COMMAND_INDEX,2 ;Move to next word in command
- MOV [BX],AX ;Put it into the buffer right here.
- ADD BX,2 ;Point to next space in buffer
- CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
- JL NO_WRAP3 ;No, readjust buffer tail
- MOV BX,OFFSET KB_BUFFER ;Yes, wrap
- NO_WRAP3:
- MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
- JMP STUFF ;Back to stuff in another character.
- BUFFER_FULL: ;If buffer is full, let timer take over
- MOV FINISHED_FLAG,0 ; by setting Finished_Flag to 0.
- NO_NEW_CHARACTERS:
- POP AX ;Restore everything before departure.
- POP BX
- POP CX
- POP DX
- POP DI
- POP SI
- POP DS
- STI
- IRET ;An interrupt deserves an IRET
- INTERCEPT_KEYBOARD_INT ENDP
- ASSUME DS:CODE_SEG
- INTERCEPT_TIMER PROC NEAR ;This completes filling the buffer
- PUSHF ;Store used flags
- PUSH DS ;Save DS since we'll change it
- PUSH CS ;Put current value of CS into DS
- POP DS
- CALL ROM_TIMER ;Make obligatory call
- PUSHF
- CMP FINISHED_FLAG,1 ;Do we have to do anything?
- JE OUT ;No, leave
- CLI ;Yes, start by clearing interrupts
- PUSH DS ;Save these.
- PUSH SI
- PUSH DX
- PUSH BX
- PUSH AX
- ASSUME DS:ROM_BIOS_DATA ;Point to the keyboard buffer again.
- MOV AX,ROM_BIOS_DATA
- MOV DS,AX
- MOV BX,ROM_BUFFER_TAIL ;Prepare to put charaters in at tail
- MOV FINISHED_FLAG,1 ;Assume we'll finish
- MOV SI,COMMAND_INDEX ;Find where we left ourselves
-
- STUFF2: MOV AX,CS:[SI] ;The same stuff loop as above.
- ADD SI,2 ;Point to next command character.
- CMP AX,0 ;Is it zero? (end of command)
- JNE OVER ;No, continue.
- JMP NO_NEW_CHARACTERS2 ;Yes, leave with Finished_Flag=1
- OVER: MOV DX,BX ;Find position in buffer from BX
- ADD DX,2 ;Move to next position for this word
- CMP DX,OFFSET KB_BUFFER_END ;Are we past the end?
- JL NO_WRAP4 ;No, don't wrap
- MOV DX,OFFSET KB_BUFFER ;Do the Wrap rap.
- NO_WRAP4:
- CMP DX,ROM_BUFFER_HEAD ;Buffer full but not yet done?
- JE BUFFER_FULL2 ;Time to leave, come back later.
- ADD COMMAND_INDEX,2 ;Point to next word of command.
- MOV [BX],AX ;Put into buffer
- ADD BX,2 ;Point to next space in buffer
- CMP BX,OFFSET KB_BUFFER_END ;Wrap here?
- JL NO_WRAP5 ;No, readjust buffer tail
- MOV BX,OFFSET KB_BUFFER ;Yes, wrap
- NO_WRAP5:
- MOV ROM_BUFFER_TAIL,BX ;Reset buffer tail
- JMP STUFF2 ;Back to stuff in another character
- BUFFER_FULL2:
- MOV FINISHED_FLAG,0 ;Set flag to not-done-yet.
- NO_NEW_CHARACTERS2:
- POP AX ;Restore these.
- POP BX
- POP DX
- POP SI
- POP DS
- OUT: POPF ;And Exit.
- POP DS
- IRET ;With customary IRET
- INTERCEPT_TIMER ENDP
-
- INIT_VECTORS PROC NEAR ;Rest Interrupt vectors here
- ASSUME DS:VECTORS
- PUSH DS
- MOV AX,VECTORS
- MOV DS,AX
- CLI ;Don't allow interrupts
- MOV AX,KEYBOARD_INT_VECTOR ;Get and store old interrupt address
- MOV ROM_KEYBOARD_INT,AX
- MOV AX,KEYBOARD_INT_VECTOR[2]
- MOV ROM_KEYBOARD_INT[2],AX
-
- MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
- MOV KEYBOARD_INT_VECTOR[2],CS ;And put ours in place.
- MOV AX,TIMER_VECTOR ;Now same for timer
- MOV ROM_TIMER,AX
- MOV AX,TIMER_VECTOR[2]
- MOV ROM_TIMER[2],AX
-
- MOV TIMER_VECTOR,OFFSET INTERCEPT_TIMER
- MOV TIMER_VECTOR[2],CS ;And intercept that too.
- STI
- ASSUME DS:ROM_BIOS_DATA
- MOV AX,ROM_BIOS_DATA
- MOV DS,AX
- MOV BX,OFFSET KB_BUFFER ;Clear the keyboard buffer.
- MOV ROM_BUFFER_HEAD,BX
- MOV ROM_BUFFER_TAIL,BX
- MOV DX,OFFSET INIT_VECTORS ;Prepare to attach in memory
- INT 27H ;And do so.
- INIT_VECTORS ENDP
- CODE_SEG ENDS
- END BEGIN ;End Begin so that we jump there first.
-